#ifndef WEBSERVER_H
#define WEBSERVER_H

#include <unordered_map>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "epoller.h"
#include "../Log/log.h"
#include "../Timer/heaptimer.h"    //最小堆定时器
#include "../Pool/sqlconnpool.h"    //sql连接池
#include "../Pool/threadpool.h"     //线程池
#include "../Http/httpconn.h"       //http连接

class WebServer
{
public:
    WebServer(
        int port, int trigMode, int timeoutMS, bool OptLinger,
        int sqlPort, const char* sqlUser, const char* sqlPwd,
        const char* dbName, int connPoolNum, int threadNum, 
        bool openLog, int logLevel, int logQueSize);
    ~WebServer();

    void Start();

private:
    bool InitSocket_();
    void InitEventMode_(int trigMode);          //设置触发模式
    void AddClient_(int fd, sockaddr_in addr);  //添加用户

    void DealListen_();
    void DealWrite_(HttpConn* client);
    void DealRead_(HttpConn* client);

    void SendError_(int fd, const char* info);
    void ExtentTime_(HttpConn* client);
    void CloseConn_(HttpConn* client);

    void OnRead_(HttpConn* client);
    void OnWrite_(HttpConn* client);
    void OnProcess(HttpConn* client);

    static const int MAX_FD = 65536;            // 最大的文件描述符个数

    static int SetFdNonblock(int fd);           // 设置文件描述符非阻塞

    int port_;          // 端口
    bool openLinger_;   // 是否打开优雅关闭
    int timeoutMS_;     // 毫秒
    bool isClose_;      // 是否关闭
    int listenFd_;      // 监听的文件描述符
    char* srcDir_;      // 资源的目录

    uint32_t listenEvent_;      // 监听的文件描述符的事件
    uint32_t connEvent_;        // 连接的文件描述符的事件

    std::unique_ptr<HeapTimer> timer_;          //创建定时器
    std::unique_ptr<ThreadPool> threadpool_;    //创建线程池
    std::unique_ptr<Epoller> epoller_;          //创建epoll包装类
    std::unordered_map<int, HttpConn> users_;   //创建用户连接
    
};

#endif